// 把 对象数据类型 转化成 查询字符串 格式
function queryStringify(obj) {
  // 目的就是把 obj 转换成 查询字符串
  // 1. 准备一个字符串
  let str = ''
  // 2. 向字符串上拼接一系列内容
  for (let k in obj) {
    // 一条数据是 key=value
    // key 就是每一次循环的 k
    // value 就是每一次循环的 obj[k]
    str += `${ k }=${ obj[k] }&`
  }
  // 3. 把字符串返回
  return str.slice(0, -1)
}

// 封装 ajax
function ajax(options) {
  // 1. 验证你传递进来的整体内容必须是一个对象数据类型
  if (Object.prototype.toString.call(options) !== '[object Object]') throw new Error('"options" 需要传递一个 Object 类型数据 ^_^')

  // 取出 options 内的所有选项, 进行一一的格式验证
  const { url, method, async, data, headers, dataType, success, error } = options

  // 2. 验证参数格式
  // 2-1. url
  if (!url || typeof url !== 'string') throw new Error('"url" 需要填写一个 String 类型数据 O(∩_∩)O哈哈~')
  // 2-2. method
  if (!(method === undefined || /^(get|post)$/i.test(method))) throw new Error('目前我只接受 "GET" 和 "POST" 请求, 请期待更新 (#^.^#)')
  // 2-3. async
  if (!(async === undefined || typeof async === 'boolean')) throw new Error('"async" 需要传递一个布尔值哦 o(*￣︶￣*)o')
  // 2-4. data
  if (!(data === undefined || typeof data === 'string' || Object.prototype.toString.call(data) === '[object Object]')) throw new Error('"data" 需要传递一个 String 或者 Object 类型数据')
  // 2-5. headers
  if (!(headers === undefined || Object.prototype.toString.call(headers) === '[object Object]')) throw new Error('"headers" 需要传递一个 Object 数据类型')
  // 2-6. dataType
  if (!(dataType === undefined || /^(string|json)$/i.test(dataType))) throw new Error('"dataType" 需要传递一个 "string" 或者 "json"')
  // 2-7. success
  if (!(success === undefined || typeof success === 'function')) throw new Error('"success" 需要传递一个 Function 数据类型')
  // 2-8. error
  if (!(error === undefined || typeof error === 'function')) throw new Error('"success" 需要传递一个 Function 数据类型')

  // 3. 准备一套默认值
  const _default = {
    url: url,
    method: method || 'GET',
    async: async ?? true,
    data: data || '',
    headers: { 'content-type': 'application/x-www-form-urlencoded', ...headers },
    dataType: dataType || 'string',
    success: success || function () {},
    error: error || function () {}
  }
  // 3-2. 默认值的操作
  // 操作 data 如果是对象数据类型, 转换成 查询字符串
  if (typeof data === 'object') _default.data = queryStringify(data)
  // 如果是 get 请求, 并且有参数, 那么直接组装一下 url 信息
  if (/^get$/i.test(_default.method) && data) _default.url += '?' + _default.data

  // 4. 发送请求
  const xhr = new XMLHttpRequest()
  xhr.open(_default.method, _default.url, _default.async)
  xhr.onload = function () {
    if (_default.dataType === 'string') return _default.success(xhr.responseText)

    // 执行解析
    try {
      let result = JSON.parse(xhr.responseText)
      _default.success(result)
    } catch(err) {
      _default.error('解析失败 ! 因为后端返回的结果不是 json 格式字符串, 请查证后再试 !!!')
    }
  }

  // 设置请求头内的信息
  for (let k in _default.headers) xhr.setRequestHeader(k, _default.headers[k])
  ;/^get$/i.test(_default.method)  ? xhr.send() : xhr.send(_default.data)
}

